#include "Application.h"
#include <iostream>

void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
    glViewport(0, 0, width, height);
}

Application::Application(/* args */)
{
    _resolutionX = 800;
    _resolutionY = 600;
    _stage = new Node();
}

Application::~Application()
{
    if (_stage)
    {
        delete _stage;
        _stage = nullptr;
    }

    // glfw: terminate, clearing all previously allocated GLFW resources.
    glfwTerminate();
}

bool Application::init()
{
    // glfw: initialize and configure
    // ------------------------------
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    // glfw window creation
    // --------------------
    _window = glfwCreateWindow(_resolutionX, _resolutionY, "LEngine", NULL, NULL);
    if (_window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(_window);
    glfwSetFramebufferSizeCallback(_window, framebuffer_size_callback);

    // glad: 加载opengl 所有的方法
    // ---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return false;
    }

    // uncomment this call to draw in wireframe polygons.
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    glViewport(0, 0, _resolutionX, _resolutionY);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


    return true;
}

void Application::run()
{
    // render loop
    while (_window && !glfwWindowShouldClose(_window))
    {
        // input
        processInput(_window);

        // render
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        if (_stage)
        {
            _stage->render();
        }
        
        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        glfwSwapBuffers(_window);
        glfwPollEvents();
    }
}

int Application::getResolutionX()
{
    return _resolutionX;
}
int Application::getResolutionY()
{
    return _resolutionY;
}
void Application::setResolution(int width, int height)
{
    _resolutionX = width;
    _resolutionY = height;
}

Node *Application::getStage()
{
    return _stage;
}